// @ts-check

/** This script modifies the project to support TS code in .svelte files like:

  <script lang="ts">
  	export let name: string;
  </script>
 
  As well as validating the code for CI.
  */

/**  To work on this script:
  rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template
*/

const fs = require("fs");
const path = require("path");
const { argv } = require("process");

const projectRoot = argv[2] || path.join(__dirname, "..");

// Add deps to pkg.json
const packageJSON = JSON.parse(
    fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")
);
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
    "svelte-check": "^2.0.0",
    "svelte-preprocess": "^4.0.0",
    "@rollup/plugin-typescript": "^8.0.0",
    typescript: "^4.0.0",
    tslib: "^2.0.0",
    "@tsconfig/svelte": "^2.0.0",
});

// Add script for checking
packageJSON.scripts = Object.assign(packageJSON.scripts, {
    check: "svelte-check --tsconfig ./tsconfig.json",
});

// Write the package JSON
fs.writeFileSync(
    path.join(projectRoot, "package.json"),
    JSON.stringify(packageJSON, null, "  ")
);

// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
const beforeMainJSPath = path.join(projectRoot, "src", "main.js");
const afterMainTSPath = path.join(projectRoot, "src", "main.ts");
fs.renameSync(beforeMainJSPath, afterMainTSPath);

// Switch the app.svelte file to use TS
const appSveltePath = path.join(projectRoot, "src", "App.svelte");
let appFile = fs.readFileSync(appSveltePath, "utf8");
appFile = appFile.replace("<script>", '<script lang="ts">');
appFile = appFile.replace("export let name;", "export let name: string;");
fs.writeFileSync(appSveltePath, appFile);

// Edit rollup config
const rollupConfigPath = path.join(projectRoot, "rollup.config.js");
let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8");

// Edit imports
rollupConfig = rollupConfig.replace(
    `'rollup-plugin-terser';`,
    `'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';`
);

// Replace name of entry point
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`);

// Add preprocessor
rollupConfig = rollupConfig.replace(
    "compilerOptions:",
    "preprocess: sveltePreprocess({ sourceMap: !production }),\n\t\t\tcompilerOptions:"
);

// Add TypeScript
rollupConfig = rollupConfig.replace(
    "commonjs(),",
    "commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),"
);
fs.writeFileSync(rollupConfigPath, rollupConfig);

// Add TSConfig
const tsconfig = `{
  "extends": "@tsconfig/svelte/tsconfig.json",

  "include": ["src/**/*"],
  "exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}`;
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
fs.writeFileSync(tsconfigPath, tsconfig);

// Add global.d.ts
const dtsPath = path.join(projectRoot, "src", "global.d.ts");
fs.writeFileSync(dtsPath, `/// <reference types="svelte" />`);

// Delete this script, but not during testing
if (!argv[2]) {
    // Remove the script
    fs.unlinkSync(path.join(__filename));

    // Check for Mac's DS_store file, and if it's the only one left remove it
    const remainingFiles = fs.readdirSync(path.join(__dirname));
    if (remainingFiles.length === 1 && remainingFiles[0] === ".DS_store") {
        fs.unlinkSync(path.join(__dirname, ".DS_store"));
    }

    // Check if the scripts folder is empty
    if (fs.readdirSync(path.join(__dirname)).length === 0) {
        // Remove the scripts folder
        fs.rmdirSync(path.join(__dirname));
    }
}

// Adds the extension recommendation
fs.mkdirSync(path.join(projectRoot, ".vscode"), { recursive: true });
fs.writeFileSync(
    path.join(projectRoot, ".vscode", "extensions.json"),
    `{
  "recommendations": ["svelte.svelte-vscode"]
}
`
);

console.log("Converted to TypeScript.");

if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
    console.log(
        "\nYou will need to re-run your dependency manager to get started."
    );
}
